/* Janet Putnam
CS 362
Assignment 4
Random Card Test - Test of adventurer card

Include the following lines in make file:


randomtestadventurer:  randomtestadventurer.c dominion.o rngs.o
	gcc -o randomtestadventurer -g randomtestadventurer.c dominion.o rngs.o $(CFLAGS)
	
randomtestadventurer.out:  randomtestadventurer
	rm -f randomtestadventurer.out
	rm -f *.gcda *.gcno *.gcov
	./randomtestadventurer 0 >> randomtestadventurer.out
	gcov -b dominion.c
	cat dominion.c.gcov >> randomtestadventurer.out

*/

#include "dominion/dominion.h"
#include "dominion/dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "dominion/rngs.h"
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

/* Copy of function from dominion.c for reference purposes, can be removed from code
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus)
...
    case adventurer:
      while(drawntreasure<2){
	if (state->deckCount[currentPlayer] <1){//if the deck is empty we need to shuffle discard and add to deck
	  shuffle(currentPlayer, state);
	}
	drawCard(currentPlayer, state);
	cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];//top card of hand is most recently drawn card.
	if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold)
	  drawntreasure++;
	else{
	  temphand[z]=cardDrawn;
	  state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one).
	  z++;
	}
      }
      while(z-1>=0){
	state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[z-1]; // discard all cards in play that have been drawn
	z=z-1;
      }
      return 0;
*/

int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus);

int adventurerTest(print_pass) {

	/* Things to test:
	1.  if deck is empty, shuffle discard and add to deck
	2.  randomly place treasure cards in deck & verify first two treasure cards are drawn
	3.  verify only two cards are added to hand & both are treasure cards
	*/
	
	//set variables
	int result; 
	int hand;
	int deck;
	int discard;
	int total;
	int i;
	int *deckCopy;
	int count;
	int random1;
	int random2;
	
	//setup initial struct gameState
	struct gameState G;
	memset(&G, 0, sizeof(struct gameState));
	
	//select cards in game
	int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, sea_hag, tribute, smithy};

	//initialize gameState struct
	initializeGame(2, k, 4, &G);
	G.whoseTurn=0;
	G.hand[0][0] = adventurer;
	
	//set variables for comparison
	hand = G.handCount[0];
	deck = G.deckCount[0];
	discard = G.discardCount[0];
	total = G.handCount[0] + G.deckCount[0] + G.discardCount[0];
	
	//make sure hand only contains no treasure cards
	for(i = 1; i < hand; i++)
	{
		G.hand[0][i] = smithy;
	}
	
	
	//allocate size of copies deck array
	deckCopy = malloc(sizeof(int) * deck);
	

	
	if (discard == 0)
	{
		//move all cards from deck to discard
		for(i = 0; i < deck; i++)
		{
			//copy 
			deckCopy[i] = G.deck[0][i];
			G.discard[0][i] = G.deck[0][i];
			G.deck[0][i] = 0;
			G.deckCount[0]--;
		}
	}
	
	else
	{
		printf("Error with moving all deck cards to discard.\n");
		return -1;
	}
	
	
	//verify deck is empty
	if (G.deckCount[0] != 0)
	{
		printf("Error with verification of empty deck.\n");
	}

	//run cardEffect for adventurer
	result = cardEffect(0, 0, 0, 0, &G, 0, 0);
	printf("Test 1:  cardEffect function called with no cards in deck.\n");
	
	//check that deck has cards
	if(G.deckCount[0] > 0)
	{
		if(print_pass == 0)
		{
			printf("PASS:  deck has cards after calling cardEffect.  Discard cards moved to deck.\n");
		}
				
	}
	else
	{
		printf("FAIL:  deck does not have cards after calling cardEffect.  Discard should have been shuffled into deck.\n");
	}

	//check that cardEffect ended w/ correct code
	if (result == 0)
	{
		if(print_pass == 0)
		{
			printf("PASS:  CardEffect function (adventurer) ended without error.\n");
		}
	}
	else
	{
		printf("FAIL:  CardEffect function (adventurer) ended with error.\n");
	}
	
	//verify two cards were added to the deck and both are treasure cards
	//since adventurer card is discarded, check that current hand count = stored hand count + 1
	if(G.handCount[0] == hand +1)
	{
		if(print_pass == 0)
		{
			printf("PASS:  Two cards were added to hand.\n");
		}
		
		//check that two cards in hand are treasure cards
		count = 0;
		for(i=0; i <G.handCount[0]; i++)
		{
			if (G.hand[0][i] == copper || G.hand[0][i] == silver || G.hand[0][i] == gold)
			{
				count++;
			}
		}
		
		if (count == 2)
		{
			if(print_pass == 0)
			{
				printf("PASS:  2 treasure cards added to hand.\n");
			}
		
		}
		else if (count < 2)
		{
			printf("FAIL:  <2 treasure cards added to hand.\n");
		}
		else
		{
			printf("FAIL:  >2 treasure cards added to hand.\n");
		}
		
	}
	else
	{
		printf("FAIL:  Two cards were not added to hand.\n");
	}
	
	//random tester for adding first two treasure cards
	//reset gameStruct 
	initializeGame(2, k, 4, &G);
	G.whoseTurn=0;
	G.hand[0][0] = adventurer;
	
	//set variables for comparison
	hand = G.handCount[0];
	deck = G.deckCount[0];
	discard = G.discardCount[0];
	total = G.handCount[0] + G.deckCount[0] + G.discardCount[0];
	
	//set deck cards to all estate
	for (i = 0; i < deck; i++)
	{
		G.deck[0][i] = estate;
	}
	
	//set two cards to randomly be copper cards
	//if there are 10 cards in deck, it fills array from 0 to 9, so % (10 - 1) for correct range
	random1 = (rand() % (deck-1));
	random2 = (rand() % (deck-1));
	
	//two random numbers cannot be equal
	while(random1 == random2)
	{
		random2 = (rand() % (deck-1));
	}
	
	G.deck[0][random1] = copper;
	G.deck[0][random2] = copper;
	
	//execute the adventure card
	result = cardEffect(0, 0, 0, 0, &G, 0, 0);
	printf("Test 2:  cardEffect function called with 2 randomly placed treasure cards in deck.\n");
	
	//check that cardEffect ended w/ correct code
	if (result == 0)
	{
		if(print_pass == 0)
		{
			printf("PASS:  CardEffect function (adventurer) ended without error.\n");
		}
	}
	else
	{
		printf("FAIL:  CardEffect function (adventurer) end with error.\n");
	}
	
	//verify two cards were added to the deck and both are treasure cards
	//since adventurer card is discarded, check that current hand count = stored hand count + 1
	if(G.handCount[0] == hand +1)
	{
		if(print_pass == 0)
		{
			printf("PASS:  Two cards were added to hand.\n");
		}
		
		//check that two cards in hand are treasure cards
		count = 0;
		for(i=0; i <G.handCount[0]; i++)
		{
			if (G.hand[0][i] == copper || G.hand[0][i] == silver || G.hand[0][i] == gold)
			{
				count++;
			}
		}
		
		if (count == 2)
		{
			if(print_pass == 0)
			{
				printf("PASS:  2 treasure cards added to hand.\n");
			}
		
		}
		else if (count < 2)
		{
			printf("FAIL:  <2 treasure cards added to hand.\n");
		}
		else
		{
			printf("FAIL:  >2 treasure cards added to hand.\n");
		}
		
	}
	else
	{
		printf("FAIL:  Two cards were not added to hand.\n");
	}
	
	//verify there are no treasure cards in the deck (both should have been added to the hand)
	count = 0;
	for(i=0; i<G.deckCount[0]; i++)
	{
		if (G.hand[0][i] == copper || G.hand[0][i] == silver || G.hand[0][i] == gold)
		{
			count++;
		}
	
	}
	if (count > 0)
	{
		printf("FAIL:  Treasure cards remain in deck that began w/ only 2 treasure cards.\n");
	}
	else
	{
		if(print_pass == 0)
		{
			printf("PASS:  No treasure cards remain in deck that began w/ only 2 treasure cards.\n");
		}
	
	}
	
	//calculate how many cards had to be removed from deck to get both treasure cards out
	if (random1 < random2)
	{
		count = deck - random2;
	}
	else
	{
		count = deck - random1;
	}
	
	if (G.deckCount[0] == count)
	{
		if(print_pass == 0)
		{
			printf("PASS:  Correct number of cards were removed from deck to get 2 treasure cards.\n");
		
		}
	}
	else if(G.deckCount[0] > count)
	{
		printf("FAIL:  Fewer cards than needed were removed from deck to get 2 treasure cards.\n");
	}
	else
	{
		printf("FAIL:  More cards were removed from deck than needed to get 2 treasure cards.\n");
	}
	
	free(deckCopy);
	
	return 0;

}


int main(int argc, char **argv)
{	
	int print_pass;
	//if print_pass = 0, then results will print for passing tests.
	//if print_pass = 1, then results will not print for passing tests.
	//regardless of print_pass state, failing tests will print results.
	
	print_pass = atoi(argv[1]);
	if ((print_pass != 1 ) || (print_pass != 0))
	{
		print_pass = 0;
	}
	
	srand(time(NULL));
	adventurerTest(print_pass);
	return 0;
}

